/* Copyright (C) 2003, Charles Wang.
 * Author:  Charles Wang <charles@linux.net.cn>
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANT; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public LIcense for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <kudzu/kudzu.h>
#include  "utils.h"
#include  "newtutils.h"
#include  "mblog.h"

char  cur_ether_module[64] = "";

static int try_load_module(const char *module);
static struct device * first_ethercard(struct device **ethers, int *pos);
static struct device * next_ethercard(struct device **ethers, int *pos);
const char * search_ether_runner(void) {
    char            cmdbuf[256];
    struct device **ethers;  int etherpos;
    struct device  *curether;
    int             i, choosed_ether, num_ethers;
    const char    * nextstep;

    if (*cur_ether_module) {
	snprintf(cmdbuf, sizeof(cmdbuf),
		 "/sbin/rmmod %s", cur_ether_module);
	if (system(cmdbuf)) {
	    mblog("Run '%s' failed.\n", cmdbuf);
	    newtWinMessage("Error", "OK",
			   "Can't rmmod %s.", cur_ether_module);
	    return  NULL;
	}
	*cur_ether_module = 0;
	mblog("Run '%s' successed.\n", cmdbuf);
    }

    ethers = probeDevices(CLASS_NETWORK, BUS_ISAPNP | BUS_PCI, PROBE_ALL);
    if (ethers == NULL) {
	newtWinMessage("Prompt", "OK",
		       "Not any ethercard is detected.");
	return  NULL;
    }

    nextstep = NULL;
    num_ethers = 0;
    for (i = 0; ethers[i] != NULL; ++i)
	if (strcmp(ethers[i]->driver, "unknown"))
	    ++num_ethers;
    if (num_ethers == 0) {
	newtWinMessage("Error", "OK",
		       "Not any recognized ethtercard is detected.\n"
		       "You might need to load drivers in driver floppy.");
	return  NULL;
    }
    if (num_ethers == 1) {
	curether = first_ethercard(ethers, &etherpos);
	if (try_load_module(curether->driver))
	    nextstep = "ethercard";
    } else {
	/* If multi-ethercards are encountered, let the user choose. */
	newtGrid       grid;
	newtComponent  form, label, listbox, cancel_btn;
	newtComponent  retco;

	grid = newtCreateGrid(1, 3);
	label = newtLabel(-1, -1, "Multi-ethercards are detected, please choose:");
	newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, label,
			 1, 1, 1, 0, NEWT_ANCHOR_LEFT, 0);
	listbox = newtListbox(-1, -1, 8,
			      NEWT_FLAG_BORDER | NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
	newtListboxSetWidth(listbox, 70);
	newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox,
			 1, 1, 1, 0, 0, 0);
	cancel_btn = newtButton(-1, -1, "Cancel");
	newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, cancel_btn,
			 1, 1, 1, 0, 0, 0);

	form = newtExtForm(NULL, NULL, 0);
	newtGridAddComponentsToForm(grid, form, 1);

	newtGridWrappedWindow(grid, "Choose ethercard");
	newtGridFree(grid, 1);

	for (curether = first_ethercard(ethers, &etherpos);
	     curether;
	     curether = next_ethercard(ethers, &etherpos))
	    newtListboxAppendEntry(listbox, curether->desc, (void *)etherpos);

	for (;;) {
	    retco = newtExtRunForm(form);
	    if (retco == cancel_btn)  break;
	    else if (retco == listbox) {
		choosed_ether = (int) newtListboxGetCurrent(listbox);
		if (try_load_module(ethers[choosed_ether]->driver)) {
		    nextstep = "ethercard";
		    break;
		}
	    }
	}

	newtFormDestroy(form);
	newtPopWindow();
    }

    for (i = 0; ethers[i] != NULL; ++i)
	freeDevice(ethers[i]);
    free(ethers);

    return  nextstep;
}

static int try_load_module(const char *module) {
    int  ret;

    ret = do_modprobe(module);
    if (ret < 0) {
	newtWinMessage("Error", "OK",
		       "Load module '%s.o' failed.\n", module);
	return  0;
    }
    if (ret == 0)
	strcpy(cur_ether_module, module);
    else
	newtWinMessage("Prompt", "OK",
		       "The module '%s.o' has been loaded already.\n",
		       module);
    return  1; /* Success. */
}

static struct device * search_ethercard(struct device **ethers, int *pos) {
    while (ethers[*pos] && !strcmp(ethers[*pos]->driver, "unknown")) ++(*pos);
    return  ethers[*pos];
}
static struct device * first_ethercard(struct device **ethers, int *pos) {
    *pos = 0;
    return  search_ethercard(ethers, pos);
}
static struct device * next_ethercard(struct device **ethers, int *pos) {
    ++(*pos);
    return  search_ethercard(ethers, pos);
}

void search_ether_saver(FILE *fp) {
    fprintf(fp, "ether_module='%s'\n", cur_ether_module);
}
